{
Traviesadora beta 0.2.0.13.33 (30.11.2008)
LastMod: 05.02.2009 by Prof1983

Copyright 2008, travieorama@googlemail.com

This file is part of the taviesadora project

taviesadora is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

taviesadora is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
}
unit NobraClientThread;

interface

uses
  Classes, Forms, Dialogs, SysUtils, IdThread, IdException, IdTcpClient, IdGlobal, InetCommunication,
  DialogWin, ChatDistributer, RosterDB, Windows, NobraChatAcceptWin, RosterGlobals;

type
  TNobraChatAcceptAnswer = (ncaNone,ncaYes,ncaAlwaysYes,ncaNo,ncaBlock);
  TNobraAcceptState = (asNothing,asAccepted,asBlocked);
  TConData = class(TObject)
  private
    TXSemaphore: RTL_CRITICAL_SECTION;
    AcceptAnswerSemaphore: RTL_CRITICAL_SECTION;
    frmAcceptAnswerSemaphore: RTL_CRITICAL_SECTION;
    ShowCloseWinSemaphore: RTL_CRITICAL_SECTION;
    TXQueue: TStringList;
    AcceptAnswer: TNobraChatAcceptAnswer;
    //frmDialogWin: TFrmDialog;
    frmAcceptNobraChat: TFrmDialog;
    ShowChatClosedWin: Boolean;
  public
    ChatDistributor: TChatDistri;
    UserID: string;
    Nick: string;
    MyPseudo: string;
    Accepted: TNobraAcceptState;
    RX: string;
    TX: TStringList;
    constructor Create(UserID,Nick,MyPseudo: string; Owner: TInetCom;initiator:boolean);
    destructor destroy;  override;
    procedure CloseChatDistri;
    procedure SendMsg(s:string);
    function GetSendMsg:string;
    procedure SetChatAcceptAnswer(AcceptAnswer:TNobraChatAcceptAnswer);
    function GetChatAcceptAnswer:TNobraChatAcceptAnswer;

    procedure SetfrmChatAcceptAnswer(frmAcceptAnswer:TFrmDialog);
    function GetfrmChatAcceptAnswer:TFrmDialog;

    procedure SetShowChatClosedWin(showit:boolean);
    function GetShowChatClosedWin:boolean;
  end;

  TNobraClientThread = class(TIdThread)
  private
    IdClient: TIdTCPClient;
    ConData: TConData;
    InsideThread_rxMsg: string;
    InsideThread_txmsg: string;
    //txmsg: string;

    SendSemaphore: RTL_CRITICAL_SECTION;
    procedure msgRxed();
    procedure ProcessInputChatString(msg: string);
    procedure ShowBockedMsgBox();
    procedure ShowClosedMsgBox();
  protected
    procedure BeforeExecute(); override;
    procedure run(); override;
    procedure AfterExecute(); override;
  public
    constructor Init(UserID,Nick,MyPseudo: string; Owner: TInetCom);
    destructor Destroy(); override;
    function GetUserID(): string;
    procedure sendMsg(msg: string);
    procedure Disconnect();
    function GetChatDistri(): TChatDistri;
    procedure SetShowChatClosedWin(showit: Boolean);
  end;

implementation

uses
  NobraProtocoll;

{ TConData }

constructor TConData.create(UserID, Nick, MyPseudo: string;
  Owner: TInetCom; initiator: boolean);
begin
  inherited create;
  TX := TStringlist.create;
  InitializeCriticalSection(TXSemaphore);
  InitializeCriticalSection(AcceptAnswerSemaphore);
  InitializeCriticalSection(frmAcceptAnswerSemaphore);
  InitializeCriticalSection(ShowCloseWinSemaphore);
  TXQueue := TStringList.Create;
  self.UserID := UserID;
  self.Nick := Nick;
  self.MyPseudo := MyPseudo;
  ShowChatClosedWin := true;
  ChatDistributor := TChatDistri.Create(nil, Owner, DelNobraRscString(MyPseudo), UserID, '', initiator, csAvailable);
  ChatDistributor.SetRmtNick(nick);
  ChatDistributor.SetUserID(UserID);
  ChatDistributor.NewVibTX(true);
  ChatDistributor.NewIncomingChatMsg('{vibtx}setconfig'+sep+'1');
  ChatDistributor.AskForPlayingVibViaChatWin;
end;

destructor TConData.destroy;
begin
  if (frmAcceptNobraChat <> nil) then
    frmAcceptNobraChat.Close;
  Tx.Free;
  inherited destroy;
end;

procedure TConData.CloseChatDistri;
begin                 
  ChatDistributor.destroy;
  TXQueue.Free;
  if frmAcceptNobraChat <> nil then
    frmAcceptNobraChat.Close;
  frmAcceptNobraChat := nil;
  ChatDistributor := nil;
  TXQueue := nil;
end;

procedure TConData.SendMsg(s: string);
begin
  EnterCriticalSection(TXSemaphore);
  TXQueue.Add(s);
  LeaveCriticalSection(TXSemaphore);
end;

function TConData.GetSendMsg: string;
begin
  result := '';
  EnterCriticalSection(TXSemaphore);
  if TXQueue.Count > 0 then begin
    result := TXQueue[0];
    TXQueue.Delete(0);
  end;
  LeaveCriticalSection(TXSemaphore);
end;

function TConData.GetChatAcceptAnswer: TNobraChatAcceptAnswer;
begin
  EnterCriticalSection(AcceptAnswerSemaphore);
  result := Self.AcceptAnswer;
  LeaveCriticalSection(AcceptAnswerSemaphore);
end;

procedure TConData.SetChatAcceptAnswer(AcceptAnswer: TNobraChatAcceptAnswer);
begin
  EnterCriticalSection(AcceptAnswerSemaphore);
  Self.AcceptAnswer := AcceptAnswer;
  LeaveCriticalSection(AcceptAnswerSemaphore);
end;

function TConData.GetfrmChatAcceptAnswer: TFrmDialog;
begin
  EnterCriticalSection(AcceptAnswerSemaphore);
  result := Self.frmAcceptNobraChat;
  LeaveCriticalSection(AcceptAnswerSemaphore);
end;

procedure TConData.SetfrmChatAcceptAnswer(
  frmAcceptAnswer: TFrmDialog);
begin
  EnterCriticalSection(AcceptAnswerSemaphore);
  Self.frmAcceptNobraChat := frmAcceptAnswer;
  LeaveCriticalSection(AcceptAnswerSemaphore);
end;

function TConData.GetShowChatClosedWin: boolean;
begin
  EnterCriticalSection(ShowCloseWinSemaphore);
  result :=  Self.ShowChatClosedWin;
  LeaveCriticalSection(ShowCloseWinSemaphore);
end;

procedure TConData.SetShowChatClosedWin(showit: boolean);
begin

  EnterCriticalSection(ShowCloseWinSemaphore);
  Self.ShowChatClosedWin := showit;
  LeaveCriticalSection(ShowCloseWinSemaphore);
end;

{ TNobraClientThread }

constructor TNobraClientThread.Init(UserID, Nick, MyPseudo: string; Owner: TInetCom);
begin
  //inherited create(False);
  FreeOnTerminate := False;
  InsideThread_rxMsg := '';
  InsideThread_txmsg := '';
  ConData := TConData.create(UserID, Nick, MyPseudo, Owner, True);
  InitializeCriticalSection(SendSemaphore);
end;

destructor TNobraClientThread.destroy;
begin
  ConData.ChatDistributor.destroy;
  inherited destroy;
end;

procedure TNobraClientThread.sendMsg(msg: string);
begin
  EnterCriticalSection(SendSemaphore);
  ConData.SendMsg(msg);
  LeaveCriticalSection(SendSemaphore);
end;



procedure TNobraClientThread.msgRxed;
begin
  ConData.ChatDistributor.NewIncomingChatMsg(InsideThread_rxMsg);
end;


procedure TNobraClientThread.ProcessInputChatString(msg:string);
begin
  InsideThread_rxMsg := msg;
  Synchronize(msgRxed);
end;

procedure TNobraClientThread.ShowClosedMsgBox;
begin
  MessageDlg('Chat closed',mtInformation,	[mbOK],0);
end;

procedure TNobraClientThread.ShowBockedMsgBox;
begin
  MessageDlg('Connection was blocked by your Partner',mtError,	[mbOK],0);
end;

procedure TNobraClientThread.BeforeExecute;
var
  s : string;
  port_:integer;
begin
  inherited;

  IdClient := TIdTCPClient.Create(nil);
  IdClient.Host := UserIDToIPPort(ConData.UserID,port_);
  IdClient.Port := port_;
  ProcessInputChatString('<constatus>Connecting..');
  IdClient.Connect;
  try
    ProcessInputChatString('<constatus>Connected');
    s := IdClient.ReadLn(LF,1000);
    if s = '<01>' then begin
      ProcessInputChatString('<constatus>Waiting for reply..');
      IdClient.Writeln('<02:'+ConData.MyPseudo+'>');
      s := IdClient.ReadLn;
      if lowercase(s) = '<03:ok>' then begin
        ProcessInputChatString('<constatus>Connection established..');
        Synchronize(ConData.ChatDistributor.ProtocollIsReadyForTransferMsgs);
        ConData.SetShowChatClosedWin(true);
      end else begin
        ConData.SetShowChatClosedWin(false);
        Synchronize(ShowBockedMsgBox);
        IdClient.Disconnect;
        stop;
      end;
    end else begin
      IdClient.Disconnect;
      stop;
    end;
  except  on EIdException do begin
            IdClient.Disconnect;
            stop;
          end;
  end;
end;

procedure TNobraClientThread.run;
var
  s : string;
begin
  try
    s := IdClient.ReadLn(LF,10);
    if not IdClient.ReadLnTimedOut then
      ProcessInputChatString(s);
    s := ConData.GetSendMsg;
    if s <> '' then begin
      IdClient.WriteLn(s);
    end;
  except  on EIdException do begin
            IdClient.Disconnect;
            stop;
          end;
  end;
end;

procedure TNobraClientThread.AfterExecute;
begin
 // inherited;
  if IdClient.Connected then
    IdClient.Disconnect;
  if ConData.GetShowChatClosedWin then
    Synchronize(ShowClosedMsgBox);
end;

function TNobraClientThread.GetUserID: string;
begin
  result := ConData.UserID;
end;

function TNobraClientThread.GetChatDistri: TChatDistri;
begin
  result := ConData.ChatDistributor;
end;

procedure TNobraClientThread.disconnect;
begin
  Synchronize(IdClient.Disconnect);
end;

procedure TNobraClientThread.SetShowChatClosedWin(showit: boolean);
begin
  ConData.SetShowChatClosedWin(showit);
end;

end.
